package fiuba.td.fabrica.view.frames;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import fiuba.td.fabrica.constants.GlobalConstants;
import fiuba.td.fabrica.controller.Controller;
import fiuba.td.fabrica.model.beans.LineaProduccionBean;
import fiuba.td.fabrica.model.entities.LineaProduccion;
import fiuba.td.fabrica.model.entities.Maquina;
import fiuba.td.fabrica.model.partida.Partida;
import fiuba.td.fabrica.services.GlobalService;

public class EdicionJDialog extends VentanaJuegoTemplate implements Observer{
	
	public EdicionJDialog(int width, int height, boolean isVisible, Observer observer) {
		super(width, height, isVisible, observer);
		
	}
	
	
	public void addConcreteCentroJPanel(Dimension dimension, Observer observer) {
		super.setCentroJPanel(new EscenarioPanel(dimension));
	}

	
	public void addConcreteEsteJPanel(Dimension dimension, Observer observer) {
		super.setEsteJPanel(new EdicionEsteJPanel(dimension));
	}

	
	public void addConcreteNorteJPanel(Dimension dimension, Observer observer) {
		super.setNorteJPanel(new EdicionNorteJPanel(dimension));
	}

	
	public void addConcreteOesteJPanel(Dimension dimension, Observer observer) {
		super.setOesteJPanel(new EdicionOesteJPanel(this.getController(), dimension, this));
	}

	
	public void addConcreteSurJPanel(Dimension dimension, Observer observer) {
		super.setSurJPanel(new EdicionSurJPanel(dimension, observer, 
				((EdicionOesteJPanel)this.getOesteJPanel()).getComboLineasProduccion(), this));
	}

	
	public void addWindowListener(Observer observer) {
		this.addWindowListener(Controller.getInstance().getEdicionWindowController(observer));		
	}

	public abstract class EdicionJPanel extends ObserverJPanel {
		protected JButton getBoton(String nombreBoton, MouseListener accionBoton){
			JButton boton = new JButton(nombreBoton);
			boton.addMouseListener(accionBoton);
			return  boton;	
		}
	}
	/**
	 * 
	 */
	private class EdicionSurJPanel extends EdicionJPanel {

		private JButton botonConfirmar;
		private JButton botonFinalizar;
		private JButton botonCrearLinea;
		private JButton botonVenderTerreno;
		private JButton botonInvertir;
		private JComboBoxObserver jComboBoxObserver;
		private Observer observer;
		private Observer obsJDialog;
		
		public EdicionSurJPanel(Dimension dimension, Observer observer, JComboBoxObserver jComboBoxObserver, Observer obsJDialog) {
			super();
			this.setLayout(new FlowLayout());
			
			this.jComboBoxObserver = jComboBoxObserver;
			this.observer = observer;
			this.obsJDialog = obsJDialog;
			this.botonConfirmar = this.getBoton(GlobalConstants.BOTON_EDICION_CONFIRMAR, Controller.getInstance().getBotonConfirmarLineaController(obsJDialog));
			this.botonFinalizar = this.getBoton(GlobalConstants.BOTON_EDICION_FINALIZAR, Controller.getInstance().getBotonFinalizarController(observer));
			this.botonCrearLinea = this.getBoton(GlobalConstants.BOTON_EDICION_CREAR_LINEA, Controller.getInstance().getBotonCrearLineaProduccionController(jComboBoxObserver, obsJDialog));
			this.botonVenderTerreno = this.getBoton(GlobalConstants.BOTON_EDICION_VENDER_TERRENO, Controller.getInstance().getBotonVenderTerrenoController(observer));
			this.botonInvertir = this.getBoton(GlobalConstants.BOTON_EDICION_INVERTIR, Controller.getInstance().getBotonInvertirController());

			this.botonConfirmar.setEnabled(false);
			this.botonFinalizar.setEnabled(false);
			
			this.add(botonConfirmar);
			this.add(botonFinalizar);
			this.add(botonCrearLinea);
			this.add(botonVenderTerreno);
			this.add(botonInvertir);			
		}
		
		private void habilitarBoton(JButton boton, MouseListener mouseListener) {
			boton.setEnabled(true);
			boton.addMouseListener(mouseListener);
		}
		
		private void deshabilitarBoton(JButton boton) {
			boton.setEnabled(false);
			for (MouseListener mouseListener : boton.getMouseListeners())
				boton.removeMouseListener(mouseListener);
		}

		
		public void update(Observable arg0, Object arg1) {
			
			GlobalConstants.PANTALLA_ACCIONES accion = (GlobalConstants.PANTALLA_ACCIONES)arg1;
		
			switch(accion){
			case DESHABILITAR_CREAR_LINEA :
				this.deshabilitarBoton(botonCrearLinea);
				this.deshabilitarBoton(botonFinalizar);
				this.deshabilitarBoton(botonVenderTerreno);
				this.habilitarBoton(botonConfirmar, Controller.getInstance().getBotonConfirmarLineaController(obsJDialog));
				break;
				
			case HABILITAR_CREAR_LINEA :
				this.deshabilitarBoton(botonConfirmar);
				this.habilitarBoton(botonCrearLinea, Controller.getInstance().getBotonCrearLineaProduccionController(jComboBoxObserver, obsJDialog));
				this.habilitarBoton(botonFinalizar, Controller.getInstance().getBotonFinalizarController(observer));
				this.habilitarBoton(botonVenderTerreno, Controller.getInstance().getBotonVenderTerrenoController(observer));
				break;
			}
		}
	}
	/**
	 * 
	 */
	public class EdicionEsteJPanel extends EdicionJPanel {
		private JTextArea lineasProduccionHelp;
		private GridBagLayout gridBagLayout;
		private GridBagConstraints constraints;
		private JScrollPane scrollPane;
		
		public EdicionEsteJPanel(Dimension dimension) {
			super();
			
			this.constraints = new GridBagConstraints();
			this.gridBagLayout = new GridBagLayout();
			this.setLayout(this.gridBagLayout);
			this.setBorder(BorderFactory.createTitledBorder("Lineas Validas"));
			this.setPreferredSize(dimension);
			Partida.getInstance().addObserver(this);
			inicializarTextArea();
		}
		
		private void inicializarTextArea() {
			this.lineasProduccionHelp = new JTextArea(15,15);
			
			this.lineasProduccionHelp.setEditable(false);
			this.lineasProduccionHelp.setLineWrap(true);
			this.lineasProduccionHelp.setWrapStyleWord(true);
			
			this.actualizarTexto();
			
			this.lineasProduccionHelp.setFont(new Font("Arial",Font.PLAIN,11));
			this.constraints.gridx = 0;
			this.constraints.gridy = 0;
			this.scrollPane = new JScrollPane(this.lineasProduccionHelp);
			this.add(this.scrollPane, this.constraints);
		}
		
		private void actualizarTexto() {
			String info = new String ("");			
			for (LineaProduccionBean linea : GlobalService.getInstance().getLineasProduccionXml()) {
				info += linea.toString() + "\n";
			}
			this.lineasProduccionHelp.setText(info);
		}

		
		public void update(Observable o, Object arg) {
			this.actualizarTexto();
		}
	}
		
	/**
	 * 
	 */
	public class EdicionOesteJPanel extends EdicionJPanel implements Observer{
		private JComboBoxObserver comboLineasProduccion;
		private JComboBox comboMaquinas;
		private JButton botonCintas;
		private JButton botonEliminarMaquina;
		private JButton botonSalidaFabrica;
		private JButton botonEliminarCinta;
		private JButton botonRepararMaquina;
		
		public JComboBoxObserver getComboLineasProduccion() {
			return comboLineasProduccion;
		}


		Font fontCombo = new Font("Arial",Font.PLAIN,11);
		GridBagConstraints constraints = new GridBagConstraints();
		public EdicionOesteJPanel(Controller controller, Dimension dimension, EdicionJDialog edicionJDialog) {
			super();
			Partida.getInstance().getFabrica().addObserver(this);
			this.setLayout(new GridBagLayout());
			this.constraints.gridx = 0;
			this.constraints.gridy= 0;
			this.constraints.weightx = this.constraints.weighty = 1;
			this.constraints.anchor = GridBagConstraints.NORTH;
			this.comboLineasProduccion = new JComboBoxObserver(getLabelsLineaProduccion());
			this.comboLineasProduccion.setFont(this.fontCombo);
			this.add(this.comboLineasProduccion,this.constraints);
			
			
			this.comboMaquinas = new JComboBox(getLabelsMaquinas());
			this.comboMaquinas.setFont(this.fontCombo);
			this.comboMaquinas.setEnabled(false);
			this.constraints.gridy = 1;
			constraints.fill = GridBagConstraints.HORIZONTAL;
			this.add(this.comboMaquinas,this.constraints);
			
			this.botonCintas = this.getBoton("Add Cinta", controller.getBotonAddCintaController());
			this.botonSalidaFabrica = this.getBoton("Add salida de fabrica", controller.getBotonAddSalidaFabricaController());
			this.botonCintas.setEnabled(false);
			this.constraints.gridy = 2;
			this.add(this.botonCintas, this.constraints);
			
			this.botonSalidaFabrica.setEnabled(false);
			this.constraints.gridy = 3;
			this.add(this.botonSalidaFabrica, this.constraints);
			this.setBorder(BorderFactory.createTitledBorder(" Opciones "));
			
			this.botonEliminarMaquina = this.getBoton("Quitar Maquina", controller.getBotonQuitarMaquinaController());
			this.botonEliminarMaquina.setEnabled(false);
			this.constraints.gridy = 4;
			this.add(this.botonEliminarMaquina, this.constraints);
			
			this.botonEliminarCinta = this.getBoton("Quitar cinta", controller.getBotonQuitarCintaController());
			this.botonEliminarCinta.setEnabled(false);
			this.constraints.gridy = 5;
			this.add(this.botonEliminarCinta, this.constraints);
			
			this.botonRepararMaquina = this.getBoton("Reparar Maquina", controller.getBotonRepararMaquinaController());
			this.botonRepararMaquina.setEnabled(false);
			this.constraints.gridy = 6;
			this.add(this.botonRepararMaquina, this.constraints);

			
			
			// Asocio los controladores para los combos
			this.comboMaquinas.addActionListener(controller.getComboMaquinaController());
			this.comboLineasProduccion.addActionListener(controller.getComboLineaProduccionController(edicionJDialog));
	
			this.setPreferredSize(dimension);
		}
		
		private Object[] getLabelsLineaProduccion(){
			List<Object> objects = new ArrayList<Object>();
			objects.add("Seleccione...");
			return objects.toArray();
		}

		private Object[] getLabelsMaquinas(){
			List<Maquina> maquinas = GlobalService.getInstance().getMaquinasXml();
			List<Object> objects = new ArrayList<Object>();
			objects.add("Seleccione...");
			objects.addAll(maquinas);
			return objects.toArray();
		}

		
		public void update(Observable arg0, Object arg1) {
			
			GlobalConstants.PANTALLA_ACCIONES accion = (GlobalConstants.PANTALLA_ACCIONES)arg1;
			
			switch(accion){
			case DESHABILITAR_CREAR_LINEA :
				this.comboMaquinas.setEnabled(true);
				this.comboLineasProduccion.setEnabled(false);
				this.botonCintas.setEnabled(true);
				this.botonSalidaFabrica.setEnabled(true);
				this.botonEliminarMaquina.setEnabled(true);
				this.botonEliminarCinta.setEnabled(true);
				this.botonRepararMaquina.setEnabled(true);
				break;
			case HABILITAR_CREAR_LINEA :
				this.comboMaquinas.setEnabled(false);
				this.comboLineasProduccion.setEnabled(true);
				this.botonCintas.setEnabled(false);
				this.botonSalidaFabrica.setEnabled(false);
				this.botonEliminarMaquina.setEnabled(false);
				this.botonEliminarCinta.setEnabled(false);
				this.botonRepararMaquina.setEnabled(false);
				break;
			}

			
		}
	}	
	
	public class JComboBoxObserver extends JComboBox implements Observer {

		public JComboBoxObserver(Object[] items) {
			super(items);
		}
		
		
		public void update(Observable arg0, Object arg1) {
			LineaProduccion lineaProduccion = (LineaProduccion)arg0;
		
			for (int i = 1; i < this.getItemCount(); i++) {
				if (this.getItemAt(i) == lineaProduccion)
					return;
			}
			
			this.addItem(lineaProduccion);
		}
		
		
		
	}
	
	public class EdicionNorteJPanel extends EdicionJPanel implements Observer {
		JLabel barraEstado; 
		public EdicionNorteJPanel(Dimension dimension){
			
			GridLayout esquema = new GridLayout(1,5,1,1);
			this.setLayout(esquema);
			this.setPreferredSize(dimension);
	
			this.barraEstado = new JLabel("Barra de estado");
			this.add(barraEstado);
			
			}
	
		public void update(Observable arg0, Object arg1) {
			
		}
	}

	
	public void update(Observable o, Object arg) {
		this.getSurJPanel().update(o, arg);
		this.getOesteJPanel().update(o, arg);
	}
	
	
}
